
import json
import re

from django import http
from django.contrib.auth import login, authenticate, logout
from django.contrib.auth.mixins import LoginRequiredMixin
from django.core.mail import send_mail
from django.http import HttpResponse, JsonResponse
from django.shortcuts import render

# Create your views here.
from django.views import View
from django_redis import get_redis_connection
from redis import Redis

from apps.goods.models import SKU
from apps.users.models import User
from apps.users.utils import generate_verify_email_url, check_verify_email_token
from celery_tasks.email.tasks import send_email_active
from utils.views import LoginRequiredJSONMixin


class UsernameCountView(View):
    def get(self,request,username):
        # 1 接收用户名
        print(username)
        print(request.user)
        # 校验数据

        # 2 根据用户名查询数据库，查询数量有几个
        try:
            count=User.objects.filter(username=username).count()
        except Exception as e:
            print(e)
            return  JsonResponse({'code': '15', 'errmsg': '数据异常'})

        count=User.objects.filter(username=username).count()
        print('count=',count)
        # 3 返回json数据
        return JsonResponse({'count':count,'code':'0','errmsg':'ok'})

        # return JsonResponse({'count': 1, 'code': '0', 'errmsg': 'ok'})




class MobileCountView(View):
    """判断手机号是否重复注册"""

    def get(self, request, mobile):
        """
        :param request: 请求对象
        :param mobile: 手机号
        :return: JSON
        """
        count = User.objects.filter(mobile=mobile).count()
        print('count', count)
        return JsonResponse({'code': 0, 'errmsg': 'OK', 'count': count})

class RegisterView(View):

    def post(self,request):
        # 接收数据，获取到json数据
        body_byte=request.body
        # 将bytes类型的数据转成JSON字符串
        data_str=body_byte.decode()
        # 把byte类型的字符串 转为字典
        data_dict=json.loads(data_str)
        username=data_dict.get('username')
        password = data_dict.get('password')
        password2 = data_dict.get('password2')
        mobile = data_dict.get('mobile')
        sms_code = data_dict.get('sms_code')
        allow = data_dict.get('allow')

        # 验证数据（数据不能为空）
        if not all([username,password,password2,mobile,sms_code,allow]):
            return JsonResponse({'code': 400, 'errmsg': '数据上传错误'})

        # 判断用户名是否是5-20个字符
        if not re.match(r'^[a-zA-Z0-9_]{5,20}$', username):
            return http.JsonResponse({'code': 400, 'errmsg': 'username格式有误!'})
        # 判断密码是否是8-20个数字
        if not re.match(r'^[0-9A-Za-z]{8,20}$', password):
            return http.JsonResponse({'code': 400, 'errmsg': 'password格式有误!'})
        # 判断两次密码是否一致
        if password != password2:
            return http.JsonResponse({'code': 400, 'errmsg': '两次输入不对!'})
        # 判断手机号是否合法
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return http.JsonResponse({'code': 400, 'errmsg': 'mobile格式有误!'})
        # 判断是否勾选用户协议
        if allow != True:
            return http.JsonResponse({'code': 400, 'errmsg': 'allow格式有误!'})

        # 判断短信验证码是否正确
        # 1.从redis取短信验证码 不要忘记decode
        redis:Redis=get_redis_connection('code')
        sms_code_redis=redis.get('smscode_%s'% mobile)

        # 2.如果没取到 说明 过期了 返回错误
        if not sms_code_redis:
            return JsonResponse({'code':400,'errmsg':'验证码过期'})
        # 3.和用户发来的对比
        sms_code_redis=sms_code_redis.decode()
        if sms_code !=sms_code_redis:
            return JsonResponse({'code':400,'errmsg':'验证码输入错误'})

        # 生成用户对象 保存到数据库
        try:
            user=User.objects.create_user(username=username,password=password,mobile=mobile)
        except Exception as e:
            print(e)
            return JsonResponse({'code':400,'errmsg':'注册失败'})

        # 把用户信息保存到session
        login(request,user)
        response = JsonResponse({'code': 0, 'errmsg': 'ok'})
        response.set_cookie('username',user.username,max_age=3600*24*15)

        # 返回响应（json）
        return response


# 登录
class LoginView(View):
    def post(self,request):
        body=request.body
        data_dict=json.loads(body)
        username=data_dict.get('username')
        password=data_dict.get('password')
        remembered=data_dict.get('remembered')

        # 2.验证数据是否为空 正则校验
        if not all([username,password,remembered]):
            return JsonResponse({'code':400,'errmsg':'写错了'})

        # username wwwwwwww 18547162936
        if re.match('^1[3-9]\d{9}$',username):
            # 手机号
            User.USERNAME_FIELD='mobile'
        else:
            # 根据用户名从数据库获取user对象返回
            User.USERNAME_FIELD='username'

        # 3.验证用户名密码是否正确
        user=authenticate(username=username,password=password)
        if not user:
            return JsonResponse({'code':400,'errmsg':'用户名密码错误'})
        # 状态保持
        login(request,user)

        # 判断是否记住登录
        if remembered:
            # 如果记住：设置为两周有效
            request.session.set_expiry(None)
        else:
            # 如果没有记住：关闭立刻失效
            request.session.set_expiry(0)

        # 返回响应
        response=JsonResponse({'code':0,'errmsg':'ok'})
        response.set_cookie('username',user.username,max_age=3600*24*15)

        return response

# 退出登录
class LogoutView(View):

    def delete(self,request):
        # 清理session
        logout(request)
        # 退出登录，重定向到登录页
        response=JsonResponse({'code':0,'errmsg':'ok'})
        # 退出登录时清除cookie中的username
        response.delete_cookie('username')
        return response

# LoginRequiredMixin
# 如果用户登录 那么正常执行视图里的函数
# 如果没有登录 视图根本 不执行
class UserInfoView(LoginRequiredJSONMixin, View):
    def get(self,request):
        # 1 取出session 里的数据 数据里有用户信息
        print(request.user.username)
        print(request.user.mobile)

        if not request.user:
            return JsonResponse({'code':400,'errmsg':'没有登录'})
        # 2 根据是否有数据 就能判断是否登录

        # 3 如果没有登录 返回code 400
        # 4 如果登录了 返回 用户名 手机号 邮箱是否激活

        return JsonResponse({'code':0,'errmsg':'ok',
                             'info_data':{
                                 'username':request.user.username,
                                 'mobile':request.user.mobile,
                                 'email':request.user.email,
                                 'email_active':request.user.email_active
                             }})

# 添加邮箱的视图
class SaveEmailView(LoginRequiredJSONMixin,View):
    def put(self,request):
        # 1.获取json数据 转为字典
        body=request.body
        data_dict=json.loads(body)
        # 2.从字典里拿到邮箱地址
        email=data_dict.get('email')
        # 3.校验
        if not email:
            return JsonResponse({'code':300,'errmsg':'邮箱不存在'})
        # 4.保存到数据库
        try:
            request.user.email=email
            request.user.save()
        except Exception as e:
            print(e)
            return  JsonResponse({'code':400,'errmsg':'保存邮箱失败'})


        # # 发送认证邮件
        # subject='我是大标题',
        # message='点我激活',
        # from_email='邢瀚<2936541941@qq.com>'
        # recipient_list=[email,'2936541941@qq.com',]
        # send_mail(subject=subject,message=message,from_email=from_email,recipient_list=recipient_list)

        # 异步发送邮件认证
        verify_url=generate_verify_email_url(request.user)
        message = '<p>尊敬的用户您好！</p>' \
                       '<p>感谢您使用美多商城。</p>' \
                       '<p>您的邮箱为：%s 。请点击此链接激活您的邮箱：</p>' \
                       '<p><a href="%s">点我激活</a></p>' % (email, verify_url)
        send_email_active.delay(email,message)

        # 5.返回响应
        return JsonResponse({'code':0,'errmsg':'ok'})


class EmailVerifyView(View):
    def put(self,request):
        # - 1 接收请求（PUT）数据
        # - 2 获取token
        token=request.GET.get('token')
        # - 3 对token解密 获取解密数据里的user_id
        user_id= check_verify_email_token(token)
        # - 5 如果获取不到 说明过期

        if not user_id:
            return JsonResponse({'code':400,'errmsg':'激活邮件已经过期'})
        # - 6 根据user_id去数据库查询
        try:
            user=User.objects.get(id=user_id)
        except Exception as e:
            print(e)
            return JsonResponse({'code':405,'errmsg':'当前用户不存在'})
        # - 7 把查到user对象的 email_active字段 改为true 不要忘记save
        user.email_active=True
        user.save()
        return JsonResponse({'code':0,'errmsg':'激活成功'})



class UserBrowseHistory(LoginRequiredJSONMixin, View):
    def post(self, request):
        # 获取当前登录的用户
        user = request.user

        # - - 接收参数
        data_dict = json.loads(request.body)
        sku_id = data_dict.get("sku_id")
        #   - 校验
        if not sku_id:
            return JsonResponse({'code': 400, 'errmsg': 'sku不存在'})

        # 去数据库查询校验
        try:
            SKU.objects.get(id=sku_id)
        except Exception as e:
            print(e)
            return JsonResponse({'code': 400, 'errmsg': 'sku不存在'})

        #   - 保存浏览数据
        redis_conn: Redis = get_redis_connection("history")
        # 获取管道
        pl = redis_conn.pipeline()
        #     - 先去重  0表示 删除所有的重复数据
        pl.lrem('history_%s' % user.id, 0, sku_id)
        #     - 存储  key包含userid 区分不同用户 的数据
        pl.lpush('history_%s' % user.id, sku_id)
        #     - 截取5个
        pl.ltrim('history_%s' % user.id, 0, 4)
        # 执行管道命令
        pl.execute()

        return JsonResponse({'code': 0, 'errmsg': 'ok'})

    def get(self, request):
        """获取用户浏览记录"""
        # 获取Redis存储的sku_id列表信息
        try:

            redis_conn = get_redis_connection('history')
            sku_ids = redis_conn.lrange('history_%s' % request.user.id, 0, -1)

            # 根据sku_ids列表数据，查询出商品sku信息
            skus = []
            for sku_id in sku_ids:
                sku = SKU.objects.get(id=sku_id)
                skus.append({
                    'id': sku.id,
                    'name': sku.name,
                    'default_image_url': sku.default_image.url,
                    'price': sku.price
                })
        except Exception as e:
            return JsonResponse({'code': 400, 'errmsg': 'data error'})

        return JsonResponse({'code': 0, 'errmsg': 'OK', 'skus': skus})
